#include "StdAfx.h"
#include "TcpPacket.h"

#include <Winsock2.h>
#pragma comment(lib, "Ws2_32.lib")


static void __TcpPacket_HexDump(const void *ptr, uint32_t buflen)
{
	unsigned char *buf = (unsigned char*)ptr;
	for(uint32_t i = 0; i < buflen; i+=16)
	{
		printf("%06x: ", i);
		for(int j = 0; j < 16; j++) 
			if(i+j < buflen)
				printf("%02x ", buf[i+j]);
			else
				printf("   ");
		printf(" ");
		for(int j = 0; j < 16; j++) 
			if(i+j < buflen)
				printf("%c", isprint(buf[i+j]) ? buf[i+j] : '.');
		printf("\n");
	}
}

bool TcpIncomingPacketProcessor::Crop(const char* streamChunk, uint32_t chunkSize, std::deque<TcpPacket*>& packets)
{
#ifdef _DEBUG
	std::cout << "[TcpIncomingPacketProcessor::Crop]" << std::endl;
	__TcpPacket_HexDump(streamChunk, chunkSize);
#endif

	buffer_.Write(streamChunk, chunkSize);

	uint8_t* buffer;
	uint32_t bufferSize;
	buffer_.GetRawData((void*&)buffer, bufferSize);

	uint32_t s = bufferSize, pos = 0, packet_size = 0;
	TcpPacket* p = NULL;

	while( s > sizeof(TcpPacket) )
	{
		p = reinterpret_cast<TcpPacket*>(buffer+pos);
		packet_size = sizeof(TcpPacket) + ntohl(p->payloadSize_);

		if( s < packet_size )
		{
			break;
		}

		if( ntohl(p->magicNumber_) == TcpPacket::MAGIC_NUMBER )
		{
			// TODO : deserialization, decryption, etc.

			p->messageId_ = ntohs(p->messageId_);
			packets.push_back(p);
		}
		else
		{
			// log
			break;
		}

		s -= packet_size;
		pos += packet_size;
	}

	if( pos > 0 )
	{
		buffer_.RemoveLeft(pos);
	}

	return false;
}


TcpPacket* TcpOutgoinigPacketProcessor::Pack(MESSAGE_ID msgId, void* payload, size_t payloadSize, size_t* packetSize)
{
	size_t totalSize = sizeof(TcpPacket)+payloadSize+1;

	buffer_.resize(totalSize);

	TcpPacket* p		= (TcpPacket*)&buffer_[0];
	p->magicNumber_		= htonl(TcpPacket::MAGIC_NUMBER);
	p->messageId_		= htons(msgId);
	p->payloadSize_		= htonl(payloadSize+1);
	::memcpy((void*)p->payload_, payload, payloadSize);

	// TODO : serialization, encryption, etc.


#ifdef _DEBUG
	std::cout << "[TcpOutgoinigPacketProcessor::Pack]" << std::endl;
	__TcpPacket_HexDump(p, totalSize);
#endif
	*packetSize = totalSize;
	return p;
}